#include"udpServer.hpp"
#include<memory>
#include<unordered_map>
#include<fstream>
#include<signal.h>

//Linux服务器做服务器端， window写一个客户端(在vs2022上)

//这里将客户端发来的消息重新发送回去，表名可以通信即可
void handlerMessage(int sockfd, string clientip, uint16_t clientport, string message)
{
    string response_message = "server echo: ";
    response_message += message;

    // 处理完之后，将信息返回给客户端【需要客户端的ip和port，以及协议等信息】
    struct sockaddr_in client; //填充结构体，如果懒得填充，可以给该函数设置一个参数，在外部传进来，可以直接用
    bzero(&client, sizeof(client));
    client.sin_family = AF_INET;
    client.sin_addr.s_addr = inet_addr(clientip.c_str()); //点分十进制ip -> int类4字节ip
    client.sin_port = htons(clientport); // 转网络字节序

    sendto(sockfd, response_message.c_str(), response_message.size(), 0, (struct sockaddr*)&client, sizeof(sockaddr_in));

    return;
}

//走到这里就是外部调用错误，没有传应该传的参数进来, 这里就提示一下
static void Usage(string proc)
{
    cout << "Usage: \n" << proc << "local_port\n";
}

// 在调用这个进程的时候要传port进来【也可以显式传ip，然后给服务器bind，但是不推荐这样做】
// ./udpServer port
int main(int argc, char* argv[])
{
    if(argc != 2) //必须得是2个元素，进程名，port。【这是命令行参数的知识，忘了就复习】
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }
    // 将argv中char*类型的port记载下来
    uint16_t port = atoi(argv[1]); //必须转成int类型，因为argv里面全是char*类型的元素
    
    //创建服务器对象
    std::unique_ptr<udpServer> usvr(new udpServer(handlerMessage, port)); //可以实现英语翻译业务逻辑

    usvr->initServer(); //初始化服务器
    usvr->start(); //启动服务器
    
    return 0;
}